<?php

namespace Upfor\UpforPHP;

use Upfor\UpforPHP\Library\Juggler;

/**
 * Basic model
 */
class Model {

    /**
     * Current table name
     *
     * @var string
     */
    public $tableName;

    /**
     * Database instance
     *
     * @var Juggler
     */
    protected $db;

    /**
     * Model constructor
     *
     * @param string|null $dbName
     */
    public function __construct($dbName = null) {
        $this->db = db($dbName);

        $this->parseTable();
    }

    /**
     * Get database instance
     *
     * @return Juggler
     */
    public function db() {
        return $this->db;
    }

    /**
     * Gets all values under the specified conditions
     *
     * @param  string  $cols
     * @param  array   $where
     * @param  string  $orderBy
     * @param  integer $offset
     * @param  integer $length
     * @return array
     */
    public function getList($cols = '*', $where = array(), $orderBy = null, $offset = 0, $length = null) {
        $this->db->table($this->getTableName())->field($cols)->where($where);
        if ($orderBy) {
            $this->db->order($orderBy);
        }

        if ($offset || $length) {
            $this->db->limit($offset, $length);
        }

        return $this->db->getList();
    }

    /**
     * Get a row of result set
     *
     * @param  string $cols
     * @param  array  $where
     * @param  string $orderBy
     * @return array
     */
    public function getRow($cols = '*', $where = array(), $orderBy = null) {
        $this->db->table($this->getTableName())->field($cols)->where($where);
        if ($orderBy) {
            $this->db->order($orderBy);
        }

        return $this->db->getRow();
    }

    /**
     * Counts the number of rows
     *
     * @param  array $where
     * @return integer
     */
    public function count($where = array()) {
        return $this->db->table($this->getTableName())->where($where)->count();
    }

    /**
     * Insert new data
     *
     * Support for bulk inserts, or updates while a duplicate value in a UNIQUE index or PRIMARY KEY
     *
     * @param  array $data    The data to insert
     * @param  mixed $replace Use sub statement `ON DUPLICATE KEY UPDATE` to replace existed data
     * @return integer
     */
    public function insert(array $data, $replace = null) {
        return $this->db->table($this->getTableName())->insert($data, $replace);
    }

    /**
     * Update data
     *
     * @param  array $data
     * @param  array $where
     * @return integer
     */
    public function update(array $data, array $where = array()) {
        return $this->db->table($this->getTableName())->where($where)->update($data);
    }

    /**
     * Delete data
     *
     * @param  array $where
     * @return integer
     */
    public function delete(array $where = array()) {
        return $this->db->table($this->getTableName())->where($where)->delete();
    }

    /**
     * Get table name
     *
     * @return string
     */
    public function getTableName() {
        return $this->tableName;
    }

    /**
     * Get table name
     *
     * @param string $tableName
     */
    public function setTableName($tableName) {
        $this->tableName = $tableName;
    }

    /**
     * Parse table name for current model
     */
    protected function parseTable() {
        $className = explode('Model', static::class, 2);
        $className = trim(array_pop($className), '\\');
        $className = str_replace('\\', '', $className);
        $className = preg_replace("/(?!^)(?=[A-Z])/", "_\$2", $className);
        $this->tableName = strtolower($className);
    }

}
